{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  Face Recognition\n",
    "\n",
    "    CNN is trained on augmented AT&T dataset. \n",
    "    \n",
    "    CNN Architecture: conv layer 1 = 300 neurons, conv layer 2 = 300 neurons, fully connected layer = 300 neurons\n",
    "    \n",
    "    Results on test set:    \n",
    "                   Precision   Recall      F1\n",
    "                    0.76      0.69      0.70\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Import packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "import numpy as np\n",
    "import cv2\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "from time import time\n",
    "import os"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Prepare data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Each image is resized to (64, 64)\n"
     ]
    }
   ],
   "source": [
    "# Handle resizing of images, while maintaing aspect ratio\n",
    "def resize_image(image, h, w):\n",
    "\n",
    "    old_width = image.shape[1]\n",
    "    old_height = image.shape[0]\n",
    "    dH, dW = 0, 0\n",
    "    \n",
    "    if old_width < old_height:  #width is smaller, resize along width and compute new height\n",
    "        aspect_r = w / old_width  #aspect ratio\n",
    "        new_height = int(old_height * aspect_r)\n",
    "        new_dim = (w, new_height)\n",
    "        resized_img = cv2.resize(image, new_dim, interpolation = cv2.INTER_AREA)\n",
    "        #dimensions of above image are: (new_height, desired_width). \n",
    "        #Since images in our dataset might be of diff. sizes, such resized images will end up being different sizes\n",
    "        #hence crop the image as follows to make each image of size(desired_height, desired_width)\n",
    "        dH = int((resized_img.shape[0] - h)/2.0)\n",
    "        \n",
    "    else:   #height is smaller, resize along height and compute new width\n",
    "        aspect_r = h / old_height  #aspect ratio\n",
    "        new_width = int(old_width * aspect_r)\n",
    "        new_dim = (new_width, h)\n",
    "        resized_img = cv2.resize(image, new_dim, interpolation = cv2.INTER_AREA)\n",
    "        dW = int((resized_img.shape[1] - w)/2.0)\n",
    "        \n",
    "    new_h, new_w = resized_img.shape[:2]\n",
    "    cropped_image = resized_img[dH:new_h - dH, dW:new_w - dW]  #dimensions of this image = desired dimensions\n",
    "    #Make sure that the image is resized to desired dimensions\n",
    "    return cv2.resize(cropped_image, (h, w), interpolation = cv2.INTER_AREA)  \n",
    "\n",
    "#All images provided to the classifier should have fixed and equal sizes\n",
    "dim = (64, 64)\n",
    "\n",
    "print(\"Each image is resized to {}\".format(dim))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Subject 0, 10 images loaded\n",
      "Subject 1, 10 images loaded\n",
      "Subject 2, 10 images loaded\n",
      "Subject 3, 10 images loaded\n",
      "Subject 4, 10 images loaded\n",
      "Subject 5, 10 images loaded\n",
      "Subject 6, 10 images loaded\n",
      "Subject 7, 10 images loaded\n",
      "Subject 8, 10 images loaded\n",
      "Subject 9, 10 images loaded\n",
      "Subject 10, 10 images loaded\n",
      "Subject 11, 10 images loaded\n",
      "Subject 12, 10 images loaded\n",
      "Subject 13, 10 images loaded\n",
      "Subject 14, 10 images loaded\n",
      "Subject 15, 10 images loaded\n",
      "Subject 16, 10 images loaded\n",
      "Subject 17, 10 images loaded\n",
      "Subject 18, 10 images loaded\n",
      "Subject 19, 10 images loaded\n",
      "Subject 20, 10 images loaded\n",
      "Subject 21, 10 images loaded\n",
      "Subject 22, 10 images loaded\n",
      "Subject 23, 10 images loaded\n",
      "Subject 24, 10 images loaded\n",
      "Subject 25, 10 images loaded\n",
      "Subject 26, 10 images loaded\n",
      "Subject 27, 10 images loaded\n",
      "Subject 28, 10 images loaded\n",
      "Subject 29, 10 images loaded\n",
      "Subject 30, 10 images loaded\n",
      "Subject 31, 10 images loaded\n",
      "Subject 32, 10 images loaded\n",
      "Subject 33, 10 images loaded\n",
      "Subject 34, 10 images loaded\n",
      "Subject 35, 10 images loaded\n",
      "Subject 36, 10 images loaded\n",
      "Subject 37, 10 images loaded\n",
      "Subject 38, 10 images loaded\n",
      "Subject 39, 10 images loaded\n"
     ]
    }
   ],
   "source": [
    "#All images provided to the classifier should have fixed and equal sizes\n",
    "dim = (64, 64)\n",
    "\n",
    "def fetch_subject_images(path_to_subject, subject_number):\n",
    "    X = np.array([])\n",
    "    index = 0\n",
    "    for subject_img in os.listdir(path_to_subject): #for each image in this subject's folder\n",
    "        img_path = os.path.join(path_to_subject, subject_img)\n",
    "        if img_path.endswith(\".pgm\") or img_path.endswith(\".png\") or img_path.endswith(\".jpg\") or img_path.endswith(\".jpeg\"):\n",
    "            #Read image, convert it to grayscale and resize every image to a fixed size  \n",
    "            img = cv2.resize(cv2.imread(img_path, 0), dim, interpolation = cv2.INTER_AREA) \n",
    "            \n",
    "            img_data = img[np.newaxis, :, :]\n",
    "            X = img_data if not X.shape[0] else np.vstack((X, img_data))\n",
    "            index += 1\n",
    "\n",
    "    y = np.empty(index, dtype = int) #index = total no. of samples\n",
    "    y.fill(subject_number)  #add labels\n",
    "    return X, y\n",
    "\n",
    "def fetch_data(dataset_path):\n",
    "\n",
    "    # Get a the list of folder names in the path to dataset\n",
    "    labels_list = [d for d in os.listdir(dataset_path) if \".\" not in str(d)]\n",
    "\n",
    "    X = np.empty([0, dim[0], dim[1]])\n",
    "    y = np.empty([0])\n",
    "\n",
    "    for i in range(0, len(labels_list)):  #for each person\n",
    "        subject = str(labels_list[i])  #person i in list of ppl\n",
    "        path_to_subject = os.path.join(dataset_path, subject) #full path to this person's directory\n",
    "        \n",
    "        #Read all images in this folder (all images of this person)\n",
    "        X_, y_ = fetch_subject_images(path_to_subject, i)\n",
    "        X = np.concatenate((X, X_), axis=0)\n",
    "        y = np.append(y, y_)\n",
    "        print(\"Subject {}, {} images loaded\".format(i, X_.shape[0]))\n",
    "\n",
    "    return X, y, labels_list\n",
    "\n",
    "# Load training data \n",
    "dataset_path = \"att_faces/\"\n",
    "X_face, y_face, labels_list  = fetch_data(dataset_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "q = labels_list\n",
    "def stringSplitByNumbers(x):\n",
    "    r = re.compile('(\\d+)')\n",
    "    l = r.split(x)\n",
    "    return [int(y) if y.isdigit() else y for y in l]\n",
    "\n",
    "labels_list_faces = sorted(q, key = stringSplitByNumbers)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  Augment data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Original data: (400, 64, 64) (400,)\n",
      "New data (1600, 64, 64) , labels (1600,)\n"
     ]
    }
   ],
   "source": [
    "def augment_data(dataset, dataset_labels, augementation_factor=1, use_random_rotation=True, use_random_shear=True, \n",
    "                 use_random_shift=True, use_random_zoom=True):\n",
    "    augmented_image = []\n",
    "    augmented_image_labels = []\n",
    "\n",
    "    for num in range (0, dataset.shape[0]):\n",
    "#         print(\"Sample {} is {} img\".format(num, dataset[num].shape))\n",
    "        # original image:\n",
    "         #convert to (1, h, w) shape\n",
    "        img_reshaped = np.array([dataset[num]])\n",
    "#         print(\"New img shape\", img_reshaped.shape)\n",
    "        augmented_image.append(img_reshaped)\n",
    "        augmented_image_labels.append(dataset_labels[num])\n",
    "\n",
    "        if use_random_rotation:\n",
    "            rotated_img= tf.keras.preprocessing.image.random_rotation(img_reshaped, 20, row_axis=1, col_axis=2, channel_axis=0)\n",
    "#             print(\"rotated image\",rotated_img.shape)\n",
    "            augmented_image.append(rotated_img)  #(1, h, w)\n",
    "            #image array should be 3D: n_channels, n_rows, n_cols\n",
    "            augmented_image_labels.append(dataset_labels[num])\n",
    "        \n",
    "        if use_random_shear:\n",
    "            rand_sheer_img = tf.keras.preprocessing.image.random_shear(img_reshaped, 0.2, row_axis=1, col_axis=2, channel_axis=0)\n",
    "            augmented_image.append(rand_sheer_img)\n",
    "            augmented_image_labels.append(dataset_labels[num])\n",
    "            \n",
    "        if use_random_shift:\n",
    "            rand_shift_img = tf.keras.preprocessing.image.random_shift(img_reshaped, 0.2, 0.2, row_axis=1, col_axis=2, channel_axis=0)\n",
    "            augmented_image.append(rand_shift_img)\n",
    "            augmented_image_labels.append(dataset_labels[num])\n",
    "            \n",
    "        if use_random_zoom:\n",
    "            zoomed_img = tf.keras.preprocessing.image.random_zoom(img_reshaped, (0.2,0.4) , row_axis=1, col_axis=2, channel_axis=0)\n",
    "            augmented_image.append(zoomed_img)\n",
    "            augmented_image_labels.append(dataset_labels[num])\n",
    "\n",
    "                \n",
    "    return np.array(augmented_image), np.array(augmented_image_labels)\n",
    "\n",
    "print(\"Original data:\", X_face.shape, y_face.shape)\n",
    "\n",
    "X_aug, y_aug = augment_data(X_face, y_face) \n",
    "X_aug = np.squeeze(X_aug)   #squeeze:  remove single-dimensional entries from shape of  array\n",
    "print(\"New data\", X_aug.shape, \", labels\", y_aug.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Split into training and test sets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dataset consists of 1600 samples and  40 classes\n",
      "Data: (1600, 64, 64) and labels: (1600, 40)\n",
      " \n",
      "Training data (1280, 64, 64), test data (320, 64, 64)\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import OneHotEncoder\n",
    "\n",
    "n_classes = len(np.unique(y_aug))\n",
    "encoder = OneHotEncoder()\n",
    "labels = encoder.fit_transform(np.reshape(y_aug, (-1, 1))).toarray()\n",
    "\n",
    "print(\"Dataset consists of {} samples and  {} classes\".format(X_aug.shape[0], n_classes))\n",
    "print(\"Data: {} and labels: {}\".format(X_aug.shape, labels.shape))                                                                                           \n",
    "print(\" \")\n",
    "X_train, X_test, y_train, y_test = train_test_split(X_aug, labels, test_size=0.20, random_state=42)\n",
    "print(\"Training data {}, test data {}\".format(X_train.shape, X_test.shape))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  CNN "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "EPOCH 0\n",
      "Train accuracy = 0.828125, train loss = 1.0985342264175415\n",
      "Validation loss: 2.5332610607147217, minimum loss: 2.5332610607147217, validation accuracy: 0.3812499940395355\n",
      " \n",
      "EPOCH 1\n",
      "Train accuracy = 0.890625, train loss = 0.6260462403297424\n",
      "Validation loss: 2.100984573364258, minimum loss: 2.100984573364258, validation accuracy: 0.637499988079071\n",
      " \n",
      "EPOCH 2\n",
      "Train accuracy = 1.0, train loss = 0.10147459805011749\n",
      "Validation loss: 1.8736355304718018, minimum loss: 1.8736355304718018, validation accuracy: 0.6312500238418579\n",
      " \n",
      "EPOCH 3\n",
      "Train accuracy = 0.953125, train loss = 0.22120465338230133\n",
      "Validation loss: 2.051478385925293, minimum loss: 1.8736355304718018, validation accuracy: 0.6781250238418579\n",
      " \n",
      "EPOCH 4\n",
      "Train accuracy = 0.984375, train loss = 0.05560923367738724\n",
      "Validation loss: 1.9996840953826904, minimum loss: 1.8736355304718018, validation accuracy: 0.699999988079071\n",
      " \n",
      "EPOCH 5\n",
      "Train accuracy = 1.0, train loss = 0.0022678396198898554\n",
      "Validation loss: 1.983088731765747, minimum loss: 1.8736355304718018, validation accuracy: 0.684374988079071\n",
      " \n",
      "EPOCH 6\n",
      "Train accuracy = 0.984375, train loss = 0.10438059270381927\n",
      "Validation loss: 1.9576705694198608, minimum loss: 1.8736355304718018, validation accuracy: 0.6781250238418579\n",
      " \n",
      "EPOCH 7\n",
      "Train accuracy = 1.0, train loss = 0.0026051956228911877\n",
      "Validation loss: 2.079479694366455, minimum loss: 1.8736355304718018, validation accuracy: 0.6875\n",
      " \n",
      "EPOCH 8\n",
      "Train accuracy = 1.0, train loss = 0.0003566499217413366\n",
      "Validation loss: 2.177675724029541, minimum loss: 1.8736355304718018, validation accuracy: 0.7093750238418579\n",
      " \n",
      "EPOCH 9\n",
      "Train accuracy = 1.0, train loss = 0.0017235385021194816\n",
      "Validation loss: 1.9899959564208984, minimum loss: 1.8736355304718018, validation accuracy: 0.7124999761581421\n",
      " \n",
      "EPOCH 10\n",
      "Train accuracy = 1.0, train loss = 0.004982644692063332\n",
      "Validation loss: 1.8570587635040283, minimum loss: 1.8570587635040283, validation accuracy: 0.6937500238418579\n",
      " \n",
      "EPOCH 11\n",
      "Train accuracy = 1.0, train loss = 0.00021089924848638475\n",
      "Validation loss: 2.118985414505005, minimum loss: 1.8570587635040283, validation accuracy: 0.7093750238418579\n",
      " \n",
      "EPOCH 12\n",
      "Train accuracy = 1.0, train loss = 0.0001617561501916498\n",
      "Validation loss: 2.1537587642669678, minimum loss: 1.8570587635040283, validation accuracy: 0.703125\n",
      " \n",
      "EPOCH 13\n",
      "Train accuracy = 1.0, train loss = 0.00010996324272127822\n",
      "Validation loss: 2.2480151653289795, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 14\n",
      "Train accuracy = 1.0, train loss = 4.239028203301132e-05\n",
      "Validation loss: 2.3850107192993164, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 15\n",
      "Train accuracy = 1.0, train loss = 8.185446495190263e-05\n",
      "Validation loss: 2.528928756713867, minimum loss: 1.8570587635040283, validation accuracy: 0.7124999761581421\n",
      " \n",
      "EPOCH 16\n",
      "Train accuracy = 1.0, train loss = 8.180395525414497e-06\n",
      "Validation loss: 2.6910412311553955, minimum loss: 1.8570587635040283, validation accuracy: 0.7093750238418579\n",
      " \n",
      "EPOCH 17\n",
      "Train accuracy = 1.0, train loss = 1.9850007447530515e-05\n",
      "Validation loss: 2.6509242057800293, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 18\n",
      "Train accuracy = 1.0, train loss = 1.9296307073091157e-05\n",
      "Validation loss: 2.6311779022216797, minimum loss: 1.8570587635040283, validation accuracy: 0.715624988079071\n",
      " \n",
      "EPOCH 19\n",
      "Train accuracy = 1.0, train loss = 6.129672328825109e-06\n",
      "Validation loss: 2.706815004348755, minimum loss: 1.8570587635040283, validation accuracy: 0.7093750238418579\n",
      " \n",
      "EPOCH 20\n",
      "Train accuracy = 1.0, train loss = 1.1361400538589805e-05\n",
      "Validation loss: 2.7892098426818848, minimum loss: 1.8570587635040283, validation accuracy: 0.7093750238418579\n",
      " \n",
      "EPOCH 21\n",
      "Train accuracy = 1.0, train loss = 1.3147170648153406e-05\n",
      "Validation loss: 2.792964458465576, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 22\n",
      "Train accuracy = 1.0, train loss = 1.0629298230924178e-05\n",
      "Validation loss: 2.816277265548706, minimum loss: 1.8570587635040283, validation accuracy: 0.7093750238418579\n",
      " \n",
      "EPOCH 23\n",
      "Train accuracy = 1.0, train loss = 8.646107744425535e-06\n",
      "Validation loss: 2.762917995452881, minimum loss: 1.8570587635040283, validation accuracy: 0.7124999761581421\n",
      " \n",
      "EPOCH 24\n",
      "Train accuracy = 1.0, train loss = 1.0621366527630016e-05\n",
      "Validation loss: 2.8017303943634033, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 25\n",
      "Train accuracy = 1.0, train loss = 6.085015229473356e-06\n",
      "Validation loss: 2.857848644256592, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 26\n",
      "Train accuracy = 1.0, train loss = 2.808829776768107e-06\n",
      "Validation loss: 2.8576087951660156, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 27\n",
      "Train accuracy = 1.0, train loss = 5.723745744035114e-06\n",
      "Validation loss: 2.900986671447754, minimum loss: 1.8570587635040283, validation accuracy: 0.703125\n",
      " \n",
      "EPOCH 28\n",
      "Train accuracy = 1.0, train loss = 1.1801306754932739e-05\n",
      "Validation loss: 2.9206786155700684, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 29\n",
      "Train accuracy = 1.0, train loss = 6.5563599491724744e-06\n",
      "Validation loss: 2.9109246730804443, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "EPOCH 30\n",
      "Train accuracy = 1.0, train loss = 5.371741281123832e-06\n",
      "Validation loss: 2.9338254928588867, minimum loss: 1.8570587635040283, validation accuracy: 0.706250011920929\n",
      " \n",
      "** EARLY STOPPING ** \n",
      "Training took 76.628630 minutes\n",
      "INFO:tensorflow:Restoring parameters from ./face_recCNN_aug1_again\n",
      "Final test accuracy = 0.6937500238418579\n"
     ]
    }
   ],
   "source": [
    "width = 64\n",
    "height = 64\n",
    "\n",
    "n_features = height*width\n",
    "channels = 1\n",
    "\n",
    "feature_map1 = 300\n",
    "ksize_conv1 = 2\n",
    "stride_conv1 = 1\n",
    "\n",
    "feature_map2 = 300\n",
    "ksize_conv2 = ksize_conv1\n",
    "stride_conv2 = stride_conv1\n",
    "\n",
    "pool_layer_maps2 = feature_map2\n",
    "\n",
    "n_fully_conn1 = 300\n",
    "  \n",
    "X = tf.placeholder(tf.float32, shape=[None, height, width])\n",
    "X_reshaped = tf.reshape(X, shape=[-1, height, width, channels])\n",
    "y = tf.placeholder(tf.int32, shape=[None, n_classes])\n",
    "\n",
    "xavier_init = tf.contrib.layers.xavier_initializer()\n",
    "relu_act = tf.nn.relu\n",
    "\n",
    "# ------------------ Convolutional and pooling layers ----------------------------\n",
    "\n",
    "def convolutional_layer(X, filter_, ksize, kernel_init, strides, padding):\n",
    "    convolutional_layer = tf.layers.conv2d(X, filters = filter_, kernel_initializer = kernel_init,\n",
    "                                           kernel_size = ksize, strides = strides,\n",
    "                                          padding = padding, activation = relu_act)\n",
    "    return convolutional_layer\n",
    "\n",
    "def pool_layer(convlayer, ksize, strides, padding, pool_maps):\n",
    "    pool = tf.nn.max_pool(convlayer, ksize, strides, padding)\n",
    "    dim1, dim2 = int(pool.get_shape()[1]), int(pool.get_shape()[2])\n",
    "    pool_flat = tf.reshape(pool, shape = [-1, pool_maps * dim1 * dim2])\n",
    "    return pool_flat\n",
    "\n",
    "conv_layer1 = convolutional_layer(X_reshaped, feature_map1, ksize_conv1, xavier_init, stride_conv1, padding = \"SAME\")\n",
    "\n",
    "conv_layer2 = convolutional_layer(conv_layer1, feature_map2, ksize_conv2, xavier_init, stride_conv2, padding = \"SAME\")\n",
    "\n",
    "pool_layer2_flat = pool_layer(conv_layer2, [1,2,2,1], [1,2,2,1], \"VALID\", pool_layer_maps2)\n",
    "\n",
    "# ----------------- Fully connected layer -------------------\n",
    "\n",
    "def dense_layer(input_layer, n_neurons, kernel_init, activation):\n",
    "    fully_conn = tf.layers.dense(inputs = input_layer, units = n_neurons, activation = activation,\n",
    "                                kernel_initializer = kernel_init)\n",
    "    return fully_conn\n",
    "        \n",
    "dense_layer1 = dense_layer(pool_layer2_flat, n_fully_conn1, xavier_init, relu_act)\n",
    "\n",
    "#--------------------------------------------------------------\n",
    "\n",
    "logits = tf.layers.dense(dense_layer1, n_classes)\n",
    "\n",
    "prediction = tf.nn.softmax(logits)\n",
    "\n",
    "xentropy = tf.nn.softmax_cross_entropy_with_logits(labels = y, logits = logits)\n",
    "loss = tf.reduce_mean(xentropy)\n",
    "\n",
    "optimizer = tf.train.AdamOptimizer(0.001)\n",
    "train_step = optimizer.minimize(loss)\n",
    "\n",
    "correct_preds = tf.equal(tf.argmax(prediction,1), tf.argmax(y, 1))\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_preds, tf.float32))\n",
    "\n",
    "saver = tf.train.Saver()\n",
    "\n",
    "n_epochs = 100\n",
    "batch_size = 64\n",
    "n_train = X_train.shape[0]\n",
    "n_iter = n_train//batch_size\n",
    "path = \"./face_recCNN_aug1_again\"\n",
    "\n",
    "train_loss_log, train_acc_log, val_loss_log, val_acc_log = ([] for i in range (4))\n",
    "\n",
    "sess = tf.InteractiveSession()\n",
    "init = tf.global_variables_initializer()\n",
    "init.run()\n",
    "\n",
    "#initialize variables for early stopping\n",
    "min_loss = np.infty\n",
    "epochs_without_improvement = 0 \n",
    "max_epochs_without_improvement = 20 \n",
    "\n",
    "start = time()\n",
    "for epoch in range(n_epochs):\n",
    "    for iteration in range(n_iter):\n",
    "        rand_indices = np.random.choice(n_train, batch_size, replace = False)    \n",
    "        X_batch, y_batch = X_train[rand_indices], y_train[rand_indices]\n",
    "        sess.run(train_step, feed_dict={X: X_batch, y: y_batch})\n",
    "        \n",
    "    train_loss, train_acc = sess.run([loss, accuracy], feed_dict={X: X_batch, y: y_batch})\n",
    "    train_loss_log.append(train_loss)\n",
    "    train_acc_log.append(train_acc)\n",
    "\n",
    "    val_loss, val_acc, y_pred = sess.run([loss, accuracy, prediction], feed_dict={X: X_test, y: y_test})\n",
    "    val_loss_log.append(val_loss)\n",
    "    val_acc_log.append(val_acc)\n",
    "        \n",
    "    # Early stopping \n",
    "        \n",
    "    if val_loss < min_loss:\n",
    "        save_path = saver.save(sess, path)\n",
    "        min_loss = val_loss\n",
    "        epochs_without_improvement = 0\n",
    "    else:\n",
    "        epochs_without_improvement += 1\n",
    "        if epochs_without_improvement > max_epochs_without_improvement:\n",
    "            print(\"** EARLY STOPPING ** \")\n",
    "            break\n",
    "    print(\"EPOCH {}\".format(epoch))\n",
    "    print(\"Train accuracy = {}, train loss = {}\".format(train_acc, train_loss))\n",
    "    print(\"Validation loss: {}, minimum loss: {}, validation accuracy: {}\".format(val_loss, min_loss, val_acc))\n",
    "    print(\" \")\n",
    "    \n",
    "print(\"Training took %f minutes\"%(float(time() - start)/60.0))\n",
    "\n",
    "saver.restore(sess, path)\n",
    "acc_test = accuracy.eval(feed_dict={X: X_test, y: y_test})\n",
    "print(\"Final test accuracy = {}\".format(acc_test))\n",
    "\n",
    "y_predicted = logits.eval(feed_dict = {X : X_test})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Inspect learning curves"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtwAAAJwCAYAAAC6d7b8AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xl4VPXZxvHvTPZlAgTClijIkgDDkhCQVYFIwQ1E2Ypo\noVqgVbRgRRFBllqIUkFAxK2tigtELLgjVoS+SNCKQTFAkFUgEJYkhqwzmTnvH8jIyJZgZg6E+3Nd\nXMyZsz3zZMR7fvnNORbDMAxERERERMQnrGYXICIiIiJSnSlwi4iIiIj4kAK3iIiIiIgPKXCLiIiI\niPiQAreIiIiIiA8pcIuIiIiI+JACt4jIJWbv3r1YrVbWr19vdikiIlIBCtwiIr/w+9//nj59+phd\nxlldeeWVHDp0iE6dOvntnB9++CE33HADderUITw8nJYtW/KnP/2J77//3m81iIhcqhS4RUQuEuXl\n5RXazmKxULduXQICAnxc0QkzZsygf//+NGvWjOXLl5OVlcU///lPQkJCmDJlyq86ttPprKIqRUQu\nXgrcIiKV5HK5mDZtGk2aNCEsLIw2bdrwwgsveG0zf/58kpKSsNlsNGjQgGHDhnHo0CHP+rVr12K1\nWvnwww+55pprCA8P5x//+AevvPIKQUFBrF+/nuTkZCIiIujQoQNfffWVZ99fTik5ufzWW2/Rv39/\nIiIiaNq0Ka+88opXTXv27KFPnz6EhYXRuHFjnn32WXr16sXo0aPP+lo3btzItGnTmDVrFgsWLOCa\na67hiiuuoEuXLjz99NM8//zzXq8nOzvba/+goCBeffVVrzrfeOMNbrrpJmw2G48++iiNGjUiNTXV\naz+Hw0F0dDT//Oc/Pc8tWLCAli1bEhYWRkJCAjNnzsTlcnnWv/POO7Rv356IiAhq1apF586d+eab\nb87+gxQR8RMFbhGRSrr77rtZsWIFL774Itu2beOxxx5j4sSJ/Otf//JsY7FYeOqpp/juu+9YsWIF\n+/btY9iwYacd68EHH2TixIls3bqVfv36AeB2u5k0aRILFiwgIyODunXrMnToUNxut9fxf+mRRx5h\nxIgRbN68md/+9rf84Q9/YMeOHZ71AwYM4Pjx46xbt453332XDz74gIyMjHO+1sWLFxMREcH48ePP\nuL5GjRrnrOlMJk6cyPDhw/nuu++49957GT58OIsXL/baZsWKFTgcDoYMGQLAtGnTmDNnDk888QTb\ntm1j3rx5vPDCC8yYMQOAnJwchgwZwvDhw9myZQsbNmxg3LhxBAYGVqgmERGfMkRExMvIkSON3/zm\nN2dct3v3bsNqtRpZWVlez8+YMcNITEw86zG//vprw2q1GtnZ2YZhGMaaNWsMi8VivP76617bvfzy\ny4bVajU2bdrkee6LL74wrFarsX37dsMwDGPPnj2GxWIxPv/8c6/lp59+2rOPy+UybDab8cILLxiG\nYRirVq0yrFarsWvXLs82ubm5Rnh4uDFq1Kiz1n3jjTca7dq1O+v6k9asWWNYrVbjwIEDXs8HBgYa\nr7zyiledf/vb37y22bZtm2G1Wo2vvvrK89zNN99s3H777YZhGEZxcbERHh5ufPzxx177vfrqq0bN\nmjUNwzCMjIwMw2q1Gnv37j1vrSIi/qaP/iIilfDVV19hGAYdOnTAMAzP8+Xl5QQFBXmW16xZQ2pq\nKlu2bCE/P98zOr13714aNGgAnBgR7tix42nnsFgstG3b1rPcsGFDDMMgJyeH5s2bn7W2du3aeR5b\nrVbq1q1LTk4OAFu3bqVOnTpcddVVnm1q1apFQkLCOV+vYRgVHrmuqF++5oSEBDp06MDixYtJTk7m\n8OHDfPzxx3zwwQcAZGZmUlJSwsCBA732c7lcOBwOjh07Rtu2benTpw92u53f/OY39OzZk9tuu424\nuLgqrV1E5EJoSomISCW43W4sFgvp6el88803nj+ZmZme+cL79u3jpptuokmTJixdupSNGzfy7rvv\nYhgGDofD63gRERGnncNqtXqF3JOPT51ScibBwcFeyxaL5bzTUM4nISGBHTt2nPcLnVbrif+dnPoh\nxO12n7HmM73mESNGsGTJElwuF2+88QYxMTH07t3bcxyAZcuWefX8u+++Y/v27URHR2O1Wvnoo4/4\n7LPPuPrqq3n77beJj4/nww8/rPRrFhGpagrcIiKVkJycDJwYqW7SpInXn5Ojx//73/8oLS1l7ty5\ndOnShebNm3Po0KEqHymujFatWnHkyBF27drleS4vL4/t27efc7877riD4uJi5syZc8b1+fn5ANSt\nWxfDMLy+NJmRkeEVwM9l2LBh/Pjjj3z00UcsXryYO+64w9Mvu91OaGgoO3fuPK3nTZo08eprhw4d\nmDhxImvXrqVHjx5e8+pFRMyiKSUiImdQWFh42hUuQkNDSUhI4Pe//z2jRo3iiSeeoEuXLhQVFbFx\n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\n5ytmO9t7sGHDhpU+lka4RURERER8yG9XKXE6nUydOpXy8nJcLhedO3dm8ODBXtscPXqUhQsXUlxc\njNvt5vbbbz/v5XBERERERC5mfgvcQUFBTJ06lZCQENxuN1OmTCEpKcnrEjT//ve/6dq1K7/5zW/Y\nv38/s2bNYuHChf4qUURERESkyvl1SklISAhwYrTb5XKdtt5isVBSUgJAcXEx0dHR/ixPRERERKTK\n+fXGN263m4kTJ5KTk0Pfvn1Pu8D64MGDefzxx/noo48oKytjypQp/ixPRERERKTK+XWE22q18uST\nT7Jo0SK+//57rwu1A6xbt46ePXuyaNEiJk6cyIIFC/xZnoiIiIhIlTPl1u7h4eHY7XY2bdrkdTvS\nzz77jEcffRSA+Ph4nE4nBQUFREVFee2fmZlJZmamZ3nIkCHYbDb/FC+nCQ4OVv9NpP6bR703l/pv\nHn/0XjdiEbMFBASc9X2elpbmeWy327Hb7ec8lt8Cd0FBAYGBgYSHh+NwONi8eTO33HKL1zZ16tTh\n22+/pWfPnuzfvx+n03la2IYzvzBdq9M8ulaqudR/86j35lL/zeOv63CLmMnlcp3xfW6z2RgyZEil\njuW3KSX5+flMnz6dCRMmMGnSJNq1a0f79u1JS0tj48aNANx55518+umnTJgwgQULFnDvvff6qzwR\nERERn0pPT/e642RKSgobNmyo0LaVNXHiRObNm3fB+5/NnDlzuO+++6r8uNWd30a4r7zySp544onT\nnj/1E0JcXJzndqQiIiIi1c2pt2VfvXp1hbc9l7S0NN58802WL1/ueS41NfXCCqyAitYlP9OdJkVE\nREQuYYZhKARf5BS4RURERCpo4cKFjB492uu5xx57jMceewyApUuX0rNnTxISEujWrRuvvfbaWY/V\nuXNn1q1bB0BpaSnjxo3DbreTkpLCN998c9p5u3XrRkJCAikpKaxcuRKAHTt2MGnSJDZu3Eh8fLzn\nO27jx49n9uzZnv1ff/11unXrRuvWrbnrrrvIycnxrIuLi2Px4sV0794du93uuYBFRaxatYqUlBTs\ndjuDBw9mx44dXjUnJyeTkJBAjx49+PzzzwHYtGkTN954Iy1atCApKYkZM2ZU+HyXKgVuERERkQoa\nMGAAn332GUVFRcCJe4y8//773HbbbQDExMSwePFisrKymDNnDtOmTeO7774773HnzJnDvn37SE9P\n5/XXX+ett97yWt+4cWNWrFhBVlYW48eP57777uPIkSM0a9aMWbNmkZyczPbt272u4nbSunXrSE1N\n5YUXXiAjI4PY2Fjuuecer20+/fRTVq5cyapVq3jvvfdYu3bteWveuXMn9957LzNmzODbb78lJSWF\nESNGUF5ezs6dO3n55ZdZuXIlWVlZvPHGG1xxxRXAiQ8of/jDH9i2bRvr16+nX79+5z3Xpc6UywKK\niIiI/BoN18RWyXGyex6o1PaxsbG0adOGlStXMnDgQNatW0dYWBiJiYnAiS9CntSpUyd69OjBl19+\nSevWrc953Pfff5/U1FSioqKIiorirrvu4umnn/asv+mmmzyP+/Xrx4IFC8jIyKBPnz7nrXnFihUM\nGzbMM/r9yCOP0KpVKw4cOEBs7Ik+jh07lsjISCIjI+natSuZmZn06NHjnMd977336N27N927dwfg\nj3/8Iy+99BJfffUV9evXx+l0sm3bNmrVquU5D5y4rOSePXvIzc0lOjqapKSk876GS50Ct4iIiFxy\nKhuUq9Itt9zCihUrGDhwICtWrODWW2/1rFu9ejVz585l165dGIZBaWkpLVu2PO8xc3JyaNCggWf5\n1PuUALz11lu8+OKLnpsGFhcXk5eXV6F6c3JyaNOmjWc5PDycWrVqcfDgQU8QjomJ8awPCwvzjOCf\n77in1mmxWGjYsCGHDh2ic+fOTJ8+nTlz5rB9+3Z69uzJY489Rr169fj73//O7Nmz6dGjB40aNWLc\nuHH07t27Qq/lUqUpJSIiIiKV0K9fP9LT0zl48CArV65kwIABADgcDkaPHs0999zD5s2b2bJlC716\n9cIwjPMes27dumRnZ3uWT70b94EDB3j44YeZOXMmW7ZsYcuWLcTHx3uOe74vTNarV48DB37+gHIy\nrJ8a8C9EvXr1TrtreHZ2NvXr1wdOfDBZvnw5X375JQAzZ84ETkyPWbhwIZs3b+ZPf/oTY8aMoaSk\n5FfVcrFT4BYRERGphOjoaLp06cIDDzzAlVdeSbNmzQBwOp04nU6io6OxWq2sXr26QnOh4edpIj/+\n+CPZ2dn861//8qwrLi7GYrEQHR2N2+1m6dKlZGVledbHxMRw8OBBnE7nGY89YMAAli5dypYtWygr\nKyM1NZX27dt7TfO4EP369ePTTz/l888/p7y8nOeee47Q0FA6dOjAzp07+fzzz3E4HAQFBREaGuq5\ne+i///1vcnNzgZ9vcFTd7yyqwC0iIiJSSQMGDGDdunVe00kiIiKYMWMGY8aMwW63884779C3b9+z\nHuPUkenx48cTGxtLly5duOOOOxg0aJBnXfPmzRkzZgz9+vUjMTGRrKwsOnbs6FnfrVs34uPjSUxM\npG3btqedp3v37kyYMIFRo0aRnJzMDz/8wLPPPnvGOs60fDZNmzZlwYIFTJ48mbZt2/Kf//yHl19+\nmcDAQBwOB7NmzaJt27a0b9+eY8eOMXHiRAA+++wzevXqRUJCAtOnT2fRokUEBwdX6JyXKotRkd9z\nXAJO/TWM+Jdur2wu9d886r251H/z+OvW7vr5ipnO9h5s2LBhpY+lEW4RERERER9S4BYRERER8SEF\nbhERERERH1LgFhERERHxIQVuEREREREfUuAWEREREfEhBW4RERERER9S4BYRERER8SEFbhERERE/\nmzhxIvPmzTO7DPETBW4RERGRSujcuTPr1q37VcdITU3lz3/+cxVVJBe7QH+dyOl0MnXqVMrLy3G5\nXHTu3JnBgweftt369etZtmwZFouFRo0acf/99/urRBEREZFfzeVyERAQYHYZPuN2u7FaNWZbGX7r\nVlBQEFOnTuXJJ59k9uzZbNq0iR07dnhtc+jQId555x0ef/xxnnrqKUaOHOmv8kRERETO6/777+fA\ngQOMHDmShIQEnnvuOfbv309cXBxLlizh6quvZujQoQCMGTOGpKQkWrVqxaBBg9i+fbvnOOPHj2f2\n7NkApKen06FDB55//nnatWtHcnIyS5cuPWsNS5cupWfPniQkJNCtWzdee+01r/Uff/wxffr0oUWL\nFnTr1o21a9cCkJ+fzwMPPEBycjJ2u50//OEPAKSlpXHrrbd6HSMuLo69e/d6an3kkUe48847iY+P\nZ/369Xz66af07duXFi1acPXVVzNnzhyv/b/88ktuueUWWrVqxdVXX81bb73FN998Q2JiIm6327Pd\nBx98QJ8+fSr1M7gU+W2EGyAkJAQ4MdrtcrlOW/+f//yHvn37Eh4eDkBUVJQ/yxMRERE5p/nz5/Pl\nl1/y1FNP0a1bNwD2798PwIYNG1i7dq1n9DclJYWnn36awMBA/va3vzF27FhWrVp1xuMeOXKEoqIi\nvv76a9auXcvo0aO54YYbzpiFYmJiWLx4MVdccQVffPEFw4cPJzExkdatW5ORkcG4ceN48cUX6d69\nOzk5ORQWFgJw3333YbPZWLNmDeHh4Xz11VeeY1osFq9z/HL5nXfeYfHixSQnJ+NwOPj666+ZP38+\nCQkJbNu2jWHDhtG6dWv69OnDgQMHuPPOO5k9ezY33XQTx48fJzs7m1atWhEdHc1///tfevbsCcDy\n5cvPOOOhuvFr4Ha73UycOJGcnBz69u1Ls2bNvNYfPHgQgClTpmAYBoMGDSIxMdGfJYqIiMglIDa2\nYZUc58CB7AvazzAMr2WLxcKDDz5IWFiY57mTI91wYpT4pZdeorCwkMjIyNOOFxQUxLhx47BaraSk\npBAREcHOnTtJSko6bduUlBTP406dOtGjRw++/PJLWrduzZIlS/jtb39L9+7dAahXrx716tXj8OHD\nrF27lszMTGw2m2ffir6+Pn36kJycDEBwcDCdO3f2rGvRogX9+/cnPT2dPn36sHz5cq699lr69+8P\nQM2aNalZsyYAgwYN4u2336Znz57k5eWxZs0aZs2addY6qgu/Bm6r1cqTTz5JcXExs2fP9vwK5iSX\ny8WhQ4eYPn06R48eZerUqTz11FOeEW8RERERuPCg7EsNGjTwPHa73aSmpvLBBx+Qm5uLxWLBYrGQ\nm5t7xsBdq1Ytr3nRYWFhFBUVnfE8q1evZu7cuezatQvDMCgtLaVly5YAZGdnc9111522T3Z2NjVr\n1vSE7cpq2ND7A05GRgYzZ84kKysLp9OJw+Hg5ptv9pyrUaNGZzzObbfdRq9evSgpKeG9996jc+fO\nxMTEXFBNlxK/Bu6TwsPDsdvtbNq0yStw165dm/j4eKxWK3Xr1qVhw4YcOnSIJk2aeO2fmZlJZmam\nZ3nIkCEX/AaSXy84OFj9N5H6bx713lzqv3n80fuL+UuHv5xucabnly9fzieffEJaWhqxsbEUFBTQ\nqlWr00aOK8vhcDB69GgWLFhA3759sVqt3H333Z7jNmzY0DP3+lQNGzYkPz+f48ePn/azCw8Pp6Sk\nxLN8+PDhc742gLFjx3LXXXfxxhtveL6nl5eX5znXpk2bzlh//fr1SU5O5sMPP+Tf//43I0aMqFwD\n/CggIOCs7/O0tDTPY7vdjt1uP+ex/Ba4CwoKCAwMJDw8HIfDwebNm7nlllu8tunYsSOff/45PXr0\noKCggIMHD1K3bt3TjnWmF3b8+HGf1i9nZ7PZ1H8Tqf/mUe/Npf6bxx+9v5g/TMXExPDDDz94PffL\nIF1YWEhwcDA1atSguLiYWbNmnTWoV4bT6cTpdBIdHY3VamX16tWsXbuWFi1aADBs2DCGDx9O7969\n6dq1q2cOd7NmzejVqxeTJk3i8ccfJyIigo0bN9KpUydatWrF9u3b2bJlC02bNmXOnDnnrbWoqIga\nNWoQFBRERkYGK1asoEePHgDceuutPPPMM7z//vvccMMNFBQUkJ2d7cluAwcOZOHChRw4cIDrr7/+\nV/fEV1wu1xnf5zabjSFDhlTqWH67Skl+fj7Tp09nwoQJTJo0iXbt2tG+fXvS0tLYuHEjAImJidhs\nNh544AH++te/cuedd57x1y4iIiIiZhk7dixPP/00drud559/Hjh9BHjw4MHExsaSnJxMSkoKHTp0\nqNQ5zhZ4IyIimDFjBmPGjMFut/POO+/Qt29fz/rExETmzJnD1KlTadGiBYMGDSI7+8T0m/nz5xMQ\nEECPHj1o164dL730EgBNmjRh3LhxDB06lGuuueacc7tPmjlzJrNnz6ZFixbMmzfPM18bIDY2lsWL\nF/Pcc89ht9vp27cvW7du9ay//vrr2b9/PzfccIPXnPfqzGL82t9tXCROvpnE/zTKZC713zzqvbnU\nf/P4a4RbP9/qq1u3bjzxxBOeL3dejM72HvzlfPaK0FXLRURERMRvPvjgAywWy0UdtquaKV+aFBER\nEZHLz6BBg9ixYwfz5883uxS/UuAWEREREb9YtmyZ2SWYQlNKRERERER8SIFbRERERMSHFLhFRERE\nRHxIgVtERERExIcUuEVEREREfEiBW0RERMQP0tPTve44mZKSwoYNGyq0bWVNnDiRefPmXfD+UrV0\nWUARERERPzn1lu2rV6+u8LbnkpaWxptvvsny5cs9z6Wmpl5YgeITGuEWERERuYQZhlHhcH6pc7lc\nZpdwQRS4RURERCpo4cKFjB492uu5xx57jMceewyApUuX0rNnTxISEujWrRuvvfbaWY/VuXNn1q1b\nB0BpaSnjxo3DbreTkpLCN998c9p5u3XrRkJCAikpKaxcuRKAHTt2MGnSJDZu3Eh8fDx2ux2A8ePH\nM3v2bM/+r7/+Ot26daN169bcdddd5OTkeNbFxcWxePFiunfvjt1u59FHHz1rzZs2baJ///60atWK\n5ORkJk+eTHl5uWd9VlYWw4YNw263k5SUxDPPPAOA2+1m/vz5ntdw4403cvDgQfbv309cXBxut9tz\njEGDBrFkyRLgxOj9gAEDmDZtGna7nTlz5rB3716GDBlC69atadu2Lffddx/Hjx/37J+dnc2oUaNo\n27Ytbdrp2nryAAAgAElEQVS0YcqUKTgcDux2O1lZWZ7tjh07RtOmTcnNzT3r660qCtwiIiIiFTRg\nwAA+++wzioqKgBNB8v333+e2224DICYmhsWLF5OVlcWcOXOYNm0a33333XmPO2fOHPbt20d6ejqv\nv/46b731ltf6xo0bs2LFCrKyshg/fjz33XcfR44coVmzZsyaNYvk5GS2b99OZmbmacdet24dqamp\nvPDCC2RkZBAbG8s999zjtc2nn37KypUrWbVqFe+99x5r1649Y50BAQFMnz6dzMxM3n33XT7//HNe\neeUVAIqKihg2bBgpKSlkZGTw+eef0717dwCef/553n33XV577TWysrJ46qmnCAsLA84/dSYjI4PG\njRuzefNm7r//fgzD4L777mPTpk2sWbOGgwcP8tRTTwEnfh4jRozgiiuu4Msvv2Tjxo3079+f4OBg\nBgwYwL///W/PcVesWMG1115LdHT0Oc9fFTSHW0RERC45sS/GVslxDow6ULnzxsbSpk0bVq5cycCB\nA1m3bh1hYWEkJiYCJ74IeVKnTp3o0aMHX375Ja1btz7ncd9//31SU1OJiooiKiqKu+66i6efftqz\n/qabbvI87tevHwsWLCAjI4M+ffqct+YVK1Z4Rp0BHnnkEVq1asWBAweIjT3Rx7FjxxIZGUlkZCRd\nu3YlMzOTHj16nHasNm3aePVi+PDhbNiwgbvvvpv//Oc/1K1bl1GjRgEQHBzs6cubb77JlClTuOqq\nqwBo2bIlAIWFheetv379+owcORKAkJAQGjduTOPGjQGIjo5m1KhRzJ07F4Cvv/6aw4cPM3nyZKzW\nE+PKHTt2BE6MnI8ePZpHHnkEgLfffvu0Dx6+osAtIiIil5zKBuWqdMstt7BixQoGDhzIihUruPXW\nWz3rVq9ezdy5c9m1axeGYVBaWuoJl+eSk5NDgwYNPMtxcXFe69966y1efPFF9u/fD0BxcTF5eXkV\nqjcnJ8crKIeHh1OrVi0OHjzoCdwxMTGe9WFhYZ4R/F/atWsX06dP59tvv6W0tJTy8nLatm0LnJjK\n0ahRozPud65159OwYUOv5WPHjjFlyhS++OILiouLcblc1KxZE4CDBw8SFxfnCdunSkpKIiIigvT0\ndGJiYti7d2+FPrBUBU0pEREREamEfv36kZ6ezsGDB1m5ciUDBgwAwOFwMHr0aO655x42b97Mli1b\n6NWrF4ZhnPeYdevWJTs727N8MlgDHDhwgIcffpiZM2eyZcsWtmzZQnx8vOe455uSUa9ePQ4c+PkD\nysmwfmrAr6hHHnmE5s2bs379erZu3crDDz/sqaNhw4bs2bPnjPvFxsaecV14eDgAJSUlnueOHDni\ntc0vX9+sWbOwWq2sXr2arVu3smDBAq8aDhw44DUn/FSDBw/m7bff5u233+amm24iODi4Qq/711Lg\nFhEREamE6OhounTpwgMPPMCVV15Js2bNAHA6nTidTqKjoz2B8GxzoX/p5DSRH3/8kezsbP71r395\n1hUXF2OxWIiOjsbtdrN06VKvL//FxMRw8OBBnE7nGY89YMAAli5dypYtWygrKyM1NZX27dt7Rrcr\no6ioiMjISMLCwtixYwevvvqqZ13v3r05evQo//jHP3A4HBQVFZGRkQHAsGHDmD17Nrt37wZg69at\n5OfnEx0dTf369Xn77bdxu90sWbKEvXv3nrOGwsJCwsPDsdlsHDx4kEWLFnnWJSUlUbduXWbOnElJ\nSQllZWX873//86y/7bbb+Oijj1i+fDmDBg2q9Ou/UArcIiIiIpU0YMAA1q1b5zWdJCIighkzZjBm\nzBjsdjvvvPMOffv2PesxTh25HT9+PLGxsXTp0oU77rjDKww2b96cMWPG0K9fPxITE8nKyvLMSwbo\n1q0b8fHxJCYmeqZ3nKp79+5MmDCBUaNGkZyczA8//MCzzz57xjrOtHyqKVOmsHz5chISEnj44Ye5\n5ZZbvF7/m2++yapVq0hKSuKaa64hPT0dgNGjR9OvXz9uv/12WrRowYQJEygtLQXgySefZNGiRbRp\n04bvv//+vDf8eeCBB9i8eTMtW7Zk5MiR3HjjjZ51VquVl19+md27d9OxY0c6duzIe++951nfoEED\n2rRpg8Vi4eqrrz7neaqSxajI7zkuAaf+Gkb8y2azeV2OR/xL/TePem8u9d88/ui9fr7iK3/5y1+o\nX78+EyZMOOd2Z3sP/nJOeUX47UuTTqeTqVOnUl5ejsvlonPnzgwePPiM227YsIG5c+cya9YsmjRp\n4q8SRURERKQa27dvHytXruTjjz/263n9FriDgoKYOnUqISEhuN1upkyZQlJSkmfe00mlpaV89NFH\nNG/e3F+liYiIiEg1N3v2bF566SXuu+++064C42t+ncMdEhICnBjtPtutOZcsWcItt9xCUFCQP0sT\nERERkWpswoQJZGVlMXbsWL+f26+B2+1289BDDzF69Gjatm172uj2nj17yM3NpX379v4sS0RERETE\nZ/x64xur1cqTTz5JcXExs2fPZv/+/Z4hfcMweOWVV7j33nvPe5zMzEyvW5cOGTIEm83ms7rl3IKD\ng9V/E6n/5lHvzaX+m8cfvQ8ICPDp8UXOJyAg4Kzv87S0NM9ju93uuYvn2Zh2lZJly5YRGhrKzTff\nDJy4xuT9999PaGgohmGQn5+PzWbjoYceqtAXJ3WVEvPom+TmUv/No96bS/03j65SIpeDS/IqJQUF\nBQQGBhIeHo7D4WDz5s1e124MDw/npZde8ixPnz6d3/3ud1x11VX+KlFEREQuEoZh6DcYZxEQEHDW\n78JJ1anKMWm/Be78/HwWLlyI2+3GMAy6du1K+/btSUtLo2nTpiQnJ5+2TzW5RLiIiIhUUmFhodkl\nXLQ0+n/p0Y1v5FfTf/jmUv/No96bS/03j3pvLvXfXBcypUS3dhcRERER8SEFbhERERERH1LgFhER\nERHxIQVuEREREREfUuAWEREREfEhBW4RERERER9S4BYRERER8SEFbhERERERH1LgFhERERHxIQVu\nEREREREfUuAWEREREfEhBW4RERERER9S4BYRERER8SEFbhERERERH1LgFhERERHxIQVuEREREREf\nUuAWEREREfEhBW4RERERER9S4BYRERER8aFAf53I6XQydepUysvLcblcdO7cmcGDB3tt8/7777N6\n9WoCAgKIioriT3/6E3Xq1PFXiSIiIiIiVc5vgTsoKIipU6cSEhKC2+1mypQpJCUl0axZM882TZo0\noU+fPgQHB7Nq1Spee+01xo0b568SRURERESqnF+nlISEhAAnRrtdLtdp61u1akVwcDAA8fHx5Obm\n+rM8EREREZEq57cRbgC3283EiRPJycmhb9++XqPbv7R69WoSExP9WJ2IiIiISNWzGIZh+PukxcXF\nzJ49m7vvvpu4uLjT1v/3v/9l1apVTJs2jcDA0z8TZGZmkpmZ6VkeMmQIx48f92nNcnbBwcE4HA6z\ny7hsqf/mUe/Npf6bR703l/pvLpvNRlpammfZbrdjt9vPuY8pgRtg2bJlhIaGcvPNN3s9/+233/Ly\nyy8zffp0bDZbhY+XnZ1d1SVKBdlsNn3gMZH6bx713lzqv3nUe3Op/+Zq2LBhpffx2xzugoICiouL\nAXA4HGzevPm0gnfv3s2LL77IQw89VKmwLSIiIiJysfLbHO78/HwWLlyI2+3GMAy6du1K+/btSUtL\no2nTpiQnJ/Paa69RVlbG3LlzMQyDOnXq8NBDD/mrRBERERGRKmfalJKqpikl5tGvtsyl/ptHvTeX\n+m8e9d5c6r+5LuopJSIiIiIilyMFbhERERERH1LgFhERERHxIQVuEREREREfUuAWEREREfEhBW4R\nERERER9S4BYRERER8SEFbhERERERH1LgFhERERHxIQVuEREREREfUuAWEREREfEhBW4RERERER9S\n4BYRERER8SEFbhERERERH1LgFhERERHxIQVuEREREREfUuAWEREREfEhBW4RERERER9S4BYRERER\n8aFAf53I6XQydepUysvLcblcdO7cmcGDB3ttU15ezjPPPMOuXbuw2WyMHz+eOnXq+KtEEREREZEq\n57fAHRQUxNSpUwkJCcHtdjNlyhSSkpJo1qyZZ5vVq1cTGRnJ/PnzWb9+Pa+99hrjxo3zV4kiIiIi\nIlXOr1NKQkJCgBOj3S6X67T1//vf/+jRowcAnTt3ZvPmzf4sT0RERESkyvlthBvA7XYzceJEcnJy\n6Nu3r9foNkBubi61a9cGwGq1EhERQWFhIZGRkf4sU0RERESkyvg1cFutVp588kmKi4uZPXs2+/fv\nJy4u7qzbG4ZxxuczMzPJzMz0LA8ZMgSbzVbl9UrFBAcHq/8mUv/No96bS/03j3pvLvXffGlpaZ7H\ndrsdu91+zu39GrhPCg8Px263s2nTJq/AXbt2bY4dO0Z0dDRut5uSkpIzjm6f6YUdP37c53XLmdls\nNvXfROq/edR7c6n/5lHvzaX+m8tmszFkyJBK7eO3OdwFBQUUFxcD4HA42Lx5Mw0bNvTaJjk5mbVr\n1wKQnp5O69at/VWeiIiIiIhP+G2EOz8/n4ULF+J2uzEMg65du9K+fXvS0tJo2rQpycnJpKSksGDB\nAu6//35sNht//vOf/VWeiIiIiIhPWIyzTZS+xGRnZ5tdwmVLv9oyl/pvHvXeXOq/edR7c1VZ/w0X\nVscx3CF1f/2xLiO/nKFREabM4RYRERER/7KWHSb4eAZBBV8TXPA1Qce/paxmN/La/NPs0qo9BW4R\n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\nDcMtt9yCb775Bps3bw55h0REREREfUlIgbuFRqPB5MmTMXny5HDXQ0REREQUU4I6tTsREREREXUN\nAzcRERERUQQxcBMRERERRRADNxERERFRBDFwExERERFFEAM3EREREVEEdWlawK5YtWoVduzYgcTE\nRCxdurTdZUpKSvD222/D5/MhISEBCxcujFZ5REREREQREbXAPWXKFFx++eVYuXJlu/fb7XasWbMG\njz76KMxmMxoaGqJVGhERERFRxERtSMmwYcNgMBg6vH/r1q0477zzYDabAQAJCQnRKo2IiIiIKGKi\ndoT7TCwWC3w+HxYtWgSn04nLL78cF110keiyiIiIiIi6pccEbr/fj59++gmPP/44XC4XHn30UeTm\n5iItLU10aUREREREXdZjArfZbEZCQgI0Gg00Gg2GDx+Ow4cPtxu4S0pKUFJSErheUFAAo9EYzXLp\nFBqNhv0XiP0Xh70Xi/0Xh70Xi/0Xr7CwMHA5Ly8PeXl5nS4f1cAtyzJkWW73vgkTJuCNN96A3++H\nx+PBgQMHMGPGjHaXbe+B2Wy2sNdLwTEajey/QOy/OOy9WOy/OOy9WOy/WEajEQUFBSGtE7XAvWLF\nCuzZswc2mw1z585FQUEBvF4vJEnCtGnTkJmZidGjR+PBBx+EQqHAtGnTkJWVFa3yiIiIiIgiQpI7\nOuTcy1gsFtEl9Fl8pS0W+y8Oey8W+y8Oey8W+y9WRkZGyOvwTJNERERERBHEwE1EREREFEEM3ERE\nREREEcTATUREREQUQQzcREREREQRxMBNRERERBRBDNxERERERBHEwE1EREREFEEM3EREREREEcTA\nTUREREQUQQzcREREREQRxMBNRERERBRBDNxERERERBHEwE1EREREFEEM3EREREREEcTATUREREQU\nQQzcREREREQRxMBNRERERBRBDNxERERERBEUtcC9atUq3HbbbXjwwQc7Xa60tBSzZ8/G119/HaXK\niIiIiIgiJ2qBe8qUKViwYEGny/j9frz77rsYM2ZMlKoiIiIiIoqsqAXuYcOGwWAwdLrMp59+iokT\nJyIhISFKVRERERERRVaPGcNttVpRVFSESy+9VHQpRERERERhoxJdQIu33noLN9xwAyRJAgDIstzh\nsiUlJSgpKQlcLygogNFojHiN1D6NRsP+C8T+i8Pei8X+i8Pei8X+i1dYWBi4nJeXh7y8vE6X7zGB\n+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\nAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f25ae9556a0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#plot the training + testing loss and accuracy\n",
    "%matplotlib inline\n",
    "plt.style.use(\"ggplot\")\n",
    "plt.figure()\n",
    "\n",
    "num_epochs_trained = len(train_loss_log)\n",
    "plt.plot(np.arange(0, num_epochs_trained), train_loss_log, label=\"train loss\", c = \"red\")\n",
    "plt.plot(np.arange(0, num_epochs_trained), val_loss_log, label=\"validation loss\",c = \"orange\")\n",
    "plt.plot(np.arange(0, num_epochs_trained), train_acc_log, label=\"train accuracy\", c = \"blue\")\n",
    "plt.plot(np.arange(0, num_epochs_trained), val_acc_log, label=\"validation accuracy\", c = \"green\")\n",
    "\n",
    "plt.title(\"Learning Curves\")\n",
    "plt.xlabel(\"Epoch number\")\n",
    "plt.ylabel(\"Accuracy/Loss\")\n",
    "plt.ylim([0, 4])\n",
    "plt.yticks(np.arange(0, 4, 0.2))\n",
    "\n",
    "plt.legend()\n",
    "\n",
    "plt.gcf().set_size_inches((12, 10))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Classification report"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Classification report:\n",
      "             precision    recall  f1-score   support\n",
      "\n",
      "         s1       0.62      1.00      0.77         5\n",
      "         s2       1.00      0.57      0.73        14\n",
      "         s3       1.00      0.67      0.80         6\n",
      "         s4       0.83      1.00      0.91         5\n",
      "         s5       1.00      0.55      0.71        11\n",
      "         s6       0.33      0.33      0.33         6\n",
      "         s7       0.78      0.64      0.70        11\n",
      "         s8       0.73      0.89      0.80         9\n",
      "         s9       1.00      0.64      0.78        11\n",
      "        s10       0.75      0.55      0.63        11\n",
      "        s11       1.00      0.67      0.80         9\n",
      "        s12       1.00      0.67      0.80         6\n",
      "        s13       0.83      0.71      0.77         7\n",
      "        s14       0.90      0.69      0.78        13\n",
      "        s15       0.79      0.92      0.85        12\n",
      "        s16       0.39      0.64      0.48        11\n",
      "        s17       0.60      0.60      0.60         5\n",
      "        s18       1.00      0.86      0.92         7\n",
      "        s19       0.45      0.83      0.59         6\n",
      "        s20       0.56      0.83      0.67         6\n",
      "        s21       0.67      0.25      0.36         8\n",
      "        s22       0.80      0.57      0.67         7\n",
      "        s23       0.67      0.75      0.71         8\n",
      "        s24       0.38      0.83      0.53         6\n",
      "        s25       0.62      0.83      0.71         6\n",
      "        s26       1.00      0.56      0.71         9\n",
      "        s27       0.43      0.60      0.50         5\n",
      "        s28       1.00      0.75      0.86        12\n",
      "        s29       0.78      0.78      0.78         9\n",
      "        s30       0.57      0.44      0.50         9\n",
      "        s31       0.80      0.67      0.73         6\n",
      "        s32       0.57      0.67      0.62         6\n",
      "        s33       0.80      0.80      0.80        10\n",
      "        s34       0.60      0.75      0.67         4\n",
      "        s35       0.50      0.60      0.55        10\n",
      "        s36       0.55      0.86      0.67         7\n",
      "        s37       0.78      1.00      0.88         7\n",
      "        s38       0.60      0.75      0.67         4\n",
      "        s39       0.50      0.88      0.64         8\n",
      "        s40       1.00      0.62      0.77         8\n",
      "\n",
      "avg / total       0.76      0.69      0.70       320\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.metrics import classification_report\n",
    "\n",
    "print(\"Classification report:\")\n",
    "print(classification_report(y_test.argmax(axis=1), y_predicted.argmax(axis=1), target_names = labels_list_faces))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
